﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using Basler.Pylon;
using System.Threading;
using hvppleDotNet;
using System.Windows.Forms;
using System.Threading.Tasks;
using HangzhouChipProject.Tools;
using HangzhouChipProject.Models;
using System.IO;

namespace HangzhouChipProject
{
    public enum tagCameraTriggerMode
    {
        /// <summary>
        /// 关闭触发
        /// </summary>
        Off = 0,

        /// <summary>
        /// 硬件触发
        /// </summary>
        Hardware = 1,

        /// <summary>
        /// 软件触发
        /// </summary>
        Software = 2,
    }

    public class clsCameraBasler
    {
        #region  ******  相机参数  ******

        /// <summary>
        /// 相机版本号，小于该版本号为网口相机，其他为usb3.0
        /// </summary>
        static Version Sfnc2_0_0 = new Version(2, 0, 0);//wells0158

        /// <summary>
        /// 相机是否正在运行 点击开始按钮 和 停止按钮 决定该状态
        /// </summary>
        public bool[] bCameraIsRunning = new bool[] { };

        /// <summary>
        /// 实际相机有没有找到，和注册表里面的相机序列号对应
        /// </summary>
        public bool[] bCameraListFind = new bool[] { };

        /// <summary>
        /// 设备打开状态标识
        /// </summary>
        public bool[] m_bIsOpen = new bool[] { };

        /// <summary>
        /// 发送开采命令标识
        /// </summary>
        public bool[] m_bIsSnap = new bool[] { };

        /// <summary>
        /// 是否支持彩色相机标识
        /// </summary>
        public bool[] bCameraIsColor = new bool[] { };

        /// <summary>
        /// 相机图片宽度
        /// </summary>
        private int[] m_nWidth = null;

        /// <summary>
        /// 相机图片高度
        /// </summary>
        private int[] m_nHeight = null;

        /// <summary>
        /// 回调次数
        /// </summary>
        public long[] lcallbackTimes = new long[11];

        /// <summary>
        /// 生成图片次数
        /// </summary>
        public long[] lgenerateImageTimes = new long[11];

        /// <summary>
        /// 相机对应的参数,【0-曝光# 1-增益 2-帧率 3-触发延时 4-旋转以及flip要求 5-触发模式 6-X是否镜像 7-Y是否镜像】
        /// </summary>
        public string[] strCameraParam = new string[] { };

        /// <summary>
        /// 相机设备
        /// </summary>
        private Camera[] myDevices = new Camera[] { };

        private long[] l_is_soft_trigger = new long[11];

        /// <summary>
        /// 是否注册回调函数
        /// </summary>
        private bool[] bRegistCallback = new bool[11];
        private int currentRow = 0; // 当前的行数
        private int currentCloumn = 0; //  当前
        private Wafers batch = new Wafers();

        /// <summary>
        /// 相机处理委托
        /// </summary>


        /// <summary>
        /// 相机硬触发委托
        /// </summary>
        public delegate void syHardTrigger();//wells0198

        /// <summary>
        /// 相机硬触发委托
        /// </summary>
        public static syHardTrigger[] dgHardTrigger = new syHardTrigger[11];//wells0198

        /// <summary>
        /// 处理函数是否使用进程锁
        /// </summary>
        private bool bUseMutexProcess = false;

        /// <summary>
        /// 处理函数进程锁
        /// </summary>
        private Mutex[] muProcess = new[] { new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex() };

        /// <summary>
        /// 回调函数是否使用进程锁
        /// </summary>
        private bool bUseMutexCallback = false;

        /// <summary>
        /// 回调函数进程锁
        /// </summary>
        private Mutex[] muCallbacks = new[] { new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex(), new Mutex() };

        /// <summary>
        /// 像素格式转换工具
        /// </summary>
        private PixelDataConverter converter = new PixelDataConverter();

        #endregion

        /// <summary>
        /// 初始化相机，自动在相机的 序列号、参数 数组的0 插入一个"0",以便相机的索引号和主界面的 1，2，3，4 对应起来
        /// </summary>
        public clsCameraBasler(string[] strCameraSn)
        {
            #region  ****** 初始化相机 ******

            try
            {
                List<string> lcamSN = new List<string>(strCameraSn);
                for (int igg = lcamSN.Count - 1; igg >= 0; igg--)
                {
                    if (lcamSN[igg] == "") lcamSN.RemoveAt(igg);
                }
                lcamSN.Insert(0, "0");
                strCameraSn = lcamSN.ToArray();

                List<string> lcamParams = new List<string>(strCameraParam);
                lcamParams.Insert(0, "0");
                strCameraParam = lcamParams.ToArray();

                bCameraListFind = new bool[strCameraSn.Length];
                bCameraIsRunning = new bool[strCameraSn.Length];
                m_bIsOpen = new bool[strCameraSn.Length];
                m_bIsSnap = new bool[strCameraSn.Length];
                bCameraIsColor = new bool[strCameraSn.Length];
                m_nWidth = new int[strCameraSn.Length];
                m_nHeight = new int[strCameraSn.Length];

                for (int igg = 0; igg < strCameraSn.Length; igg++)
                {
                    bCameraListFind[igg] = false;    //初始化相机是否找到标示符
                    bCameraIsRunning[igg] = false;//初始化相机运行状态
                    m_bIsOpen[igg] = false;          // 初始化设备开启标示符
                    m_bIsSnap[igg] = false;         // 初始化设备开始采集标示符
                    bCameraIsColor[igg] = false;
                }

                myDevices = new Camera[strCameraSn.Length];

                List<ICameraInfo> allcamerainfo = CameraFinder.Enumerate();//查找所有可连接相机

                #region 把查找到的相机按照序列号进行匹配

                for (uint ihh = 0; ihh < strCameraSn.Length; ihh++)
                {
                    for (int iCamNumber = 0; iCamNumber < allcamerainfo.Count; iCamNumber++)
                    {
                        //获取相机的序列号
                        ICameraInfo icamerainfo = allcamerainfo.ElementAt(iCamNumber);
                        string value = icamerainfo[CameraInfoKey.SerialNumber];//"21803199"
                        //判定是不是指定的相机
                        if (strCameraSn[ihh] == value)
                        {
                            bCameraListFind[ihh] = true;
                            myDevices[ihh] = new Camera(icamerainfo);
                            break;
                        }
                    }
                }

                #endregion

                #region 对找到的相机进行初始化设置

                if (myDevices.Length > 0)
                {
                    for (int icamNumber = 0; icamNumber < myDevices.Length; icamNumber++)
                    {
                        if (!bCameraListFind[icamNumber]) continue;

                        /*打开相机*/
                        myDevices[icamNumber].Open();

                        /* 设置为黑白格式*/
                        //myDevices[icamNumber].Parameters[PLCamera.PixelFormat].TrySetValue(PLCamera.PixelFormat.Mono8);

                        /* 设置为硬触发模式*/
                        //myDevices[icamNumber].Parameters[PLCamera.TriggerSelector].TrySetValue(PLCamera.TriggerSelector.FrameStart);
                        //myDevices[icamNumber].Parameters[PLCamera.TriggerMode].TrySetValue(PLCamera.TriggerMode.On);
                        //myDevices[icamNumber].Parameters[PLCamera.TriggerSource].TrySetValue(PLCamera.TriggerSource.Line1);

                        /* 设置曝光时间*/
                        //myDevices[icamNumber].Parameters[PLCamera.ExposureTimeAbs].TrySetValue(3500);

                        /* 设置采集模式为连续采集*/
                        myDevices[icamNumber].Parameters[PLCamera.AcquisitionMode].TrySetValue(PLCamera.AcquisitionMode.Continuous);

                        /* 设置网口数据包*/
                        //myDevices[icamNumber].Parameters[PLCamera.GevSCPSPacketSize].TrySetValue(1500);

                        if (myDevices[icamNumber].GetSfncVersion() < Sfnc2_0_0) //wells0158
                        {
                            myDevices[icamNumber].Parameters[PLCamera.GevHeartbeatTimeout].TrySetValue(5000);//wells0007
                            myDevices[icamNumber].Parameters[PLCamera.GevSCPSPacketSize].TrySetValue(8000);//需要开启网卡巨型帧设置
                        }

                        myDevices[icamNumber].Parameters[PLCameraInstance.MaxNumBuffer].TrySetValue(20); //wells0195

                        /* 设置回调函数*/

                        registCamCallback(icamNumber);

                        bCameraListFind[icamNumber] = true;
                        m_bIsOpen[icamNumber] = myDevices[icamNumber].IsOpen;
                        //bCameraIsColor[icamNumber] = "None" != myDevices[icamNumber].Parameters[PLCamera.PixelColorFilter].GetValue();
                        bCameraIsColor[icamNumber] = IsColorPixelFormat(myDevices[icamNumber].Parameters[PLCamera.PixelFormat].GetValue());//wells0158
                        m_nWidth[icamNumber] = (int)myDevices[icamNumber].Parameters[PLCamera.Width].GetValue();
                        m_nHeight[icamNumber] = (int)myDevices[icamNumber].Parameters[PLCamera.Height].GetValue();
                    }
                }

                #endregion
            }
            catch (Exception exc)
            {
                //string strErrorInfo = "Error Detail:" + exc.ToDetailString();
                ////Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(216), "Basler") + strErrorInfo, 2, 2);
            }

            #endregion
        }

        #region ***** 相机控制接口 *****

        public void startCameras(int icamIndex)//wells0141
        {
            #region  ****** 启动相机采集图像  ******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg] && !bCameraIsRunning[igg])
                    {
                        int iTryTime = 0;
                        bool bFail = true;

                    RESTART:
                        try
                        {
                            string triggerModeStr = myDevices[igg].Parameters[PLCamera.TriggerMode].GetValue();
                            string triggerSourceStr = myDevices[igg].Parameters[PLCamera.TriggerSource].GetValue();

                            if (triggerModeStr == "On" && triggerSourceStr == "Software")
                                myDevices[igg].StreamGrabber.Start(1000);
                            else
                                myDevices[igg].StreamGrabber.Start(GrabStrategy.OneByOne, GrabLoop.ProvidedByStreamGrabber);

                            bFail = false;
                        }
                        catch (Exception eee)
                        {
                            bFail = true;
                            iTryTime++;

                            if (iTryTime < 10)
                                goto RESTART;
                        }

                        if ((!myDevices[igg].StreamGrabber.IsGrabbing || bFail) && iTryTime < 10)
                        {
                            bFail = true;
                            goto RESTART;
                        }

                        if (!bFail)
                        {
                            bCameraIsRunning[igg] = true;
                            m_bIsSnap[igg] = true;
                        }
                        else
                        {
                            ////Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(217), "Basler", icamIndex) + "重新开启采集无效", 2);
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                ////Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(217), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void stopCameras(int icamIndex)
        {
            #region  ****** 停止相机采集图像  ******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg] && bCameraIsRunning[igg])
                    {
                        myDevices[igg].StreamGrabber.Stop();
                        bCameraIsRunning[igg] = false;
                        m_bIsSnap[igg] = false;
                    }
                }
            }
            catch (Exception exc)
            {
                ////Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(218), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void closeCameras()
        {
            #region ****** 关闭相机 ******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if (bCameraListFind[igg])
                    {
                        // 如果未停采则先停止采集
                        if (m_bIsSnap[igg])
                        {
                            stopCameras(igg);
                        }

                        myDevices[igg].Close();
                        m_bIsOpen[igg] = false;
                    }
                }
            }
            catch (Exception exc)
            {
                ////Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(219), "Basler") + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void setCameraTriggerMode(int icamIndex, int eCamTrigger)
        {
            #region   ****** 设置相机触发模式  ******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        if (eCamTrigger == (int)tagCameraTriggerMode.Off)
                        {
                            myDevices[igg].Parameters[PLCamera.TriggerSelector].TrySetValue(PLCamera.TriggerSelector.FrameStart);
                            myDevices[igg].Parameters[PLCamera.TriggerMode].TrySetValue(PLCamera.TriggerMode.Off);
                            registCamCallback(igg);
                        }
                        else if (eCamTrigger == (int)tagCameraTriggerMode.Hardware)
                        {
                            myDevices[igg].Parameters[PLCamera.TriggerSelector].TrySetValue(PLCamera.TriggerSelector.FrameStart);
                            myDevices[igg].Parameters[PLCamera.TriggerMode].TrySetValue(PLCamera.TriggerMode.On);
                            myDevices[igg].Parameters[PLCamera.TriggerSource].TrySetValue(PLCamera.TriggerSource.Line1);
                            registCamCallback(igg);
                        }
                        else if (eCamTrigger == (int)tagCameraTriggerMode.Software)
                        {
                            myDevices[igg].Parameters[PLCamera.TriggerSelector].TrySetValue(PLCamera.TriggerSelector.FrameStart);
                            myDevices[igg].Parameters[PLCamera.TriggerMode].TrySetValue(PLCamera.TriggerMode.On);
                            myDevices[igg].Parameters[PLCamera.TriggerSource].TrySetValue(PLCamera.TriggerSource.Software);
                            unregistCamCallback(igg);
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(220), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void setCameraTriggerDelay(int icamIndex, int delay)
        {
            #region  ******  设置相机触发延时  ******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        myDevices[igg].Parameters[PLCamera.TriggerDelay].TrySetValue(delay);
                    }
                }
            }
            catch (Exception exc)
            {
                //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(227), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void setCameraExpose(int icamIndex, int expose)
        {
            #region  ****** 设置相机曝光 *******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        if (myDevices[igg].GetSfncVersion() < Sfnc2_0_0)//wells0158
                            myDevices[igg].Parameters[PLCamera.ExposureTimeAbs].TrySetValue(expose);
                        else
                            myDevices[igg].Parameters[PLUsbCamera.ExposureTime].TrySetValue(expose);
                    }
                }
            }
            catch (Exception exc)
            {
                //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(222), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void setCameraGain(int icamIndex, int gain)
        {
            #region  ****** 设置相机增益 *******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        myDevices[igg].Parameters[PLCamera.GainAuto].TrySetValue(PLCamera.GainAuto.Off);

                        if (myDevices[igg].GetSfncVersion() < Sfnc2_0_0)//wells0158
                            myDevices[igg].Parameters[PLCamera.GainRaw].TrySetValue(gain);
                        else
                            myDevices[igg].Parameters[PLUsbCamera.Gain].TrySetValue(gain);
                    }
                }
            }
            catch (Exception exc)
            {
                //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(223), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            #endregion
        }

        public void getCameraExposeLimit(int icamIndex, ref double min, ref double max)
        {
            #region  ****** 获取相机曝光限定 *******

            try
            {
                if (bCameraListFind[icamIndex])
                {
                    if (myDevices[icamIndex].GetSfncVersion() < Sfnc2_0_0)//wells0158
                    {
                        min = myDevices[icamIndex].Parameters[PLCamera.AutoExposureTimeAbsLowerLimit].GetValue();
                        max = myDevices[icamIndex].Parameters[PLCamera.AutoExposureTimeAbsUpperLimit].GetValue();
                    }
                    else
                    {
                        min = myDevices[icamIndex].Parameters[PLUsbCamera.AutoExposureTimeLowerLimit].GetValue();
                        max = myDevices[icamIndex].Parameters[PLUsbCamera.AutoExposureTimeUpperLimit].GetValue();
                    }
                }
                else
                {
                    min = 0;
                    max = 50000;
                }
            }
            catch (Exception exc)
            {
                ////Wells.FrmType.frm_Log.Log("获取水星相机曝光参数出错<" + icamIndex.ToString() + ">:" + exc.ToDetailString(), 2, 2);
            }

            #endregion
        }

        public void getCameraGainLimit(int icamIndex, ref double min, ref double max)
        {
            #region  ****** 获取相机增益限定 *******

            try
            {
                if (bCameraListFind[icamIndex])
                {
                    if (myDevices[icamIndex].GetSfncVersion() < Sfnc2_0_0)//wells0158
                    {
                        min = myDevices[icamIndex].Parameters[PLCamera.AutoGainRawLowerLimit].GetValue();
                        max = myDevices[icamIndex].Parameters[PLCamera.AutoGainRawUpperLimit].GetValue();
                    }
                    else
                    {
                        min = myDevices[icamIndex].Parameters[PLUsbCamera.AutoGainLowerLimit].GetValue();
                        max = myDevices[icamIndex].Parameters[PLUsbCamera.AutoGainUpperLimit].GetValue();
                    }
                }
                else
                {
                    min = 0;
                    max = 24;
                }
            }
            catch (Exception exc)
            {
                ////Wells.FrmType.frm_Log.Log("获取水星相机增益参数出错<" + icamIndex.ToString() + ">:" + exc.ToDetailString(), 2, 2);
            }

            #endregion
        }

        public void setCameraParam(int icamIndex)
        {
            #region  ****** 设置相机参数 *******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        //【0 - 曝光# 1-增益 2-帧率 3-触发延时 4-旋转以及flip要求 5-触发模式 6-X是否镜像 7-Y是否镜像 】
                        string[] strParam = strCameraParam[igg].Split('#');

                        int iexposure = int.Parse(strParam[0]);
                        int igainraw = int.Parse(strParam[1]);
                        int itriggerdelay = int.Parse(strParam[3]);
                        int itriggermode = int.Parse(strParam[5]);

                        setCameraExpose(igg, iexposure);
                        setCameraGain(igg, igainraw);
                        setCameraTriggerDelay(igg, itriggerdelay);
                        setCameraTriggerMode(igg, itriggermode);
                    }
                }
            }
            catch (Exception exc)
            {

            }

            #endregion
        }

        public bool doSoftTrigger(int icamIndex)//wells0209
        {
            #region  ****** 软触发相机 ******

            bool bResult = false;

            try
            {
                if (bCameraListFind[icamIndex])
                {
                    int iTryTime = 0;
                    bool bFail = true;

                    string errMsg = "";

                RESTART://wells0213.1//触发添加重新触发机制
                    try
                    {
                        if (myDevices[icamIndex].WaitForFrameTriggerReady(1000, TimeoutHandling.ThrowException))//wells0148//采用确认机制再触发？
                        {
                            myDevices[icamIndex].ExecuteSoftwareTrigger();
                            bFail = false;
                        }
                    }
                    catch (Exception eee)
                    {
                        bFail = true;
                        iTryTime++;
                        errMsg = eee.ToString();

                        if (iTryTime < 10)
                            goto RESTART;
                    }

                    if (bFail && iTryTime < 10)
                        goto RESTART;

                    if (!bFail)
                    {
                        bResult = true;
                    }
                    else
                    {
                        //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(224), "Basler", icamIndex) + errMsg + "，重启无效！", 2);
                    }
                }
            }
            catch (Exception exc)
            {
                bResult = false;
                //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(224), "Basler", icamIndex) + exc.ToDetailString(), 2);
            }

            return bResult;

            #endregion
        }

        public bool doHardTrigger(int icamIndex)//wells0198//wells0209
        {
            #region  ****** 硬触发相机 ******

            bool bResult = false;

            try
            {
                if (bCameraListFind[icamIndex])
                {
                    if (myDevices[icamIndex].WaitForFrameTriggerReady(1000, TimeoutHandling.ThrowException))//wells0148//采用确认机制再触发？
                    {
                        Interlocked.Exchange(ref l_is_soft_trigger[icamIndex], 0);
                        if (dgHardTrigger[icamIndex] != null)
                        {
                            dgHardTrigger[icamIndex]();
                            while (Interlocked.Read(ref l_is_soft_trigger[icamIndex]) == 0) { Thread.Sleep(1); }
                            if (Interlocked.Read(ref l_is_soft_trigger[icamIndex]) == 1)
                                bResult = true;
                        }
                        Interlocked.Exchange(ref l_is_soft_trigger[icamIndex], 0);
                    }
                }
            }
            catch (Exception exc)
            {
                bResult = false;
          
            }

            return bResult;

            #endregion
        }

        public void setCameraOutputOn(int icamIndex, int iport)
        {
            #region  ***** 设置相机 对应相机和端口的状态为ON *****

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        myDevices[igg].Parameters[PLCamera.LineSelector].TrySetValue(PLCamera.LineSelector.Out1);
                        myDevices[igg].Parameters[PLCamera.LineSource].TrySetValue(PLCamera.LineSource.UserOutput);
                        myDevices[igg].Parameters[PLCamera.UserOutputSelector].TrySetValue(PLCamera.UserOutputSelector.UserOutput1);
                        myDevices[igg].Parameters[PLCamera.UserOutputValue].TrySetValue(true);

                        bool bstate = myDevices[igg].Parameters[PLCamera.UserOutputValue].GetValue();
                    }
                }
            }
            catch (Exception exc)
            {
                //dhDll.frmMsg.Log("设置相机输出信号On出错<" + icamIndex.ToString() + ">:" + exc.ToDetailString(), dhDll.logDiskMode.Error, MessageBoxIcon.Error);
            }

            #endregion
        }

        public void setCameraOutputOff(int icamIndex, int iport)
        {
            #region  ***** 设置相机 对应相机和端口的状态为OFF *****

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                    }
                }
            }
            catch (Exception exc)
            {
                //dhDll.frmMsg.Log("设置相机输出信号Off出错，请检查相机:" + exc.ToDetailString(), dhDll.logDiskMode.Error, MessageBoxIcon.Error);
            }

            #endregion
        }

        public long getCameraCallbackCount(int icamIndex)
        {
            #region  ****** 获取相机回调次数 *******

            return Interlocked.Read(ref lcallbackTimes[icamIndex]);

            #endregion
        }

        public void resetCameraCallbackCount(int icamIndex)
        {
            #region  ****** 重置相机回调次数 *******
            for (int igg = 0; igg < myDevices.Length; igg++)
            {
                if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                {
                    lcallbackTimes[igg] = 0;
                }
            }
            #endregion
        }

        public int getCameraFoundCount()
        {
            #region ***** 获取当前连接相机数量 *****

            int count = 0;
            for (int igg = 0; igg < myDevices.Length; igg++)
            {
                if (bCameraListFind[igg]) count++;
            }
            return count;

            #endregion
        }

        public void setCameraTriggleRate(int icamIndex, bool enable, double rate)
        {
            #region  ****** 设置相机采集帧率 *******

            try
            {
                for (int igg = 0; igg < myDevices.Length; igg++)
                {
                    if ((icamIndex == 888 || icamIndex == igg) && bCameraListFind[igg])
                    {
                        myDevices[igg].Parameters[PLCamera.AcquisitionFrameRateEnable].TrySetValue(enable);
                        myDevices[igg].Parameters[PLCamera.AcquisitionFrameRateAbs].TrySetValue(rate);
                    }
                }
            }
            catch (Exception exc)
            {
                //dhDll.frmMsg.Log("设置Basler相机采集帧率参数出错<" + icamIndex.ToString() + ">:" + exc.ToDetailString(), dhDll.logDiskMode.Error, MessageBoxIcon.None);
            }

            #endregion
        }

        public void setCameraContrast(int icamIndex, int contrast)
        {
            #region  ****** 设置相机对比度 *******

            try
            {

            }
            catch (Exception exc)
            {
                //dhDll.frmMsg.Log("设置Basler相机对比度参数出错<" + icamIndex.ToString() + ">:" + exc.ToDetailString(), dhDll.logDiskMode.Error, MessageBoxIcon.None);
            }

            #endregion
        }

        #endregion

        #region ***** 相机回调函数 *****

        private void Cam1_CallbackPro(Object sender, ImageGrabbedEventArgs e)//wells0195
        {
            #region   ****** 1号相机回调函数 ******
            int iCamIndex = 1;
            if (bUseMutexCallback) muCallbacks[iCamIndex].WaitOne();

            try
            {
                if (!Directory.Exists(@"D:\Ngs\" + batch.Id))
                {                     //如果不存在就创建file文件夹                     
                    Directory.CreateDirectory(@"D:\Ngs\" + batch.Id);
                }
                Interlocked.Increment(ref lcallbackTimes[iCamIndex]);
                if (!m_bIsSnap[iCamIndex]) return;
                IGrabResult grabResult = e.GrabResult;
                if (!grabResult.GrabSucceeded)
                {
                    System.Console.Out.WriteLine("图片采集不成功：" + grabResult.ErrorDescription);
                    //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(225), iCamIndex) + "，图片采集不成功：" + grabResult.ErrorDescription, 2);
                    return;
                }

                Interlocked.Increment(ref lgenerateImageTimes[iCamIndex]);

                Bitmap b = GrabResult2Bmp(grabResult);

                if (currentRow % 2 == 0)
                {
                    if (++currentCloumn > batch.AllColumn)
                    {
                        currentRow++;
                        currentCloumn = batch.AllColumn;
                    }
                }
                else
                {
                    if (--currentCloumn < 0)
                    {
                        currentRow++;
                        currentCloumn = 0;
                    }
                }
                #region 一系列检测
                List<Ng> ngs = new List<Ng>(); // 随便一个，我是算法返回的缺陷信息
                ngs.Add(new Ng()
                {
                    NgType = "缺陷1",
                    rect = new Rectangle(13, 14, 20, 30),
                });
                ngs.Add(new Ng()
                {
                    NgType = "缺陷2",
                    rect = new Rectangle(2018, 11, 21, 17),
                });
                #endregion
                string waferPath = Path.Combine(batch.BasePath, "Wafers");
                if (!Directory.Exists(waferPath))
                {                     //如果不存在就创建file文件夹                     
                    Directory.CreateDirectory(waferPath);
                }

                OneWafer oneWafer = new OneWafer()
                {
                    Column = currentCloumn,
                    Row = currentRow,
                    Status = ngs.Count > 0 ? 1 : 0,
                    Ngs = ngs,
                    ImgPath = Path.Combine(waferPath, iCamIndex + "-R" + currentRow + "_C" + currentCloumn + ".jpg"),
                };
                batch.wafers.Add(oneWafer);
                b.Save(oneWafer.ImgPath, ImageFormat.Jpeg);
            }
            catch (Exception exc)
            {
                //Wells.FrmType.frm_Log.Log(string.Format(clsLanguage.getString(225), iCamIndex) + exc.ToDetailString(), 2);
            }
            finally
            {
                e.DisposeGrabResultIfClone();
                if (bUseMutexCallback) muCallbacks[iCamIndex].ReleaseMutex();
            }
            //MySmartThreadPool.Instance().QueueWorkItem((iCamIndex) => {


            //}, 1);
            #endregion
        }

        private void Cam2_CallbackPro(Object sender, ImageGrabbedEventArgs e)//wells0195
        {
            #region   ****** 2号相机回调函数 ******
            
            #endregion
        }

        private void Cam3_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 3号相机回调函数 ******



            #endregion
        }

        private void Cam4_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 4号相机回调函数 ******



            #endregion
        }

        private void Cam5_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 5号相机回调函数 ******



            #endregion
        }

        private void Cam6_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 6号相机回调函数 ******



            #endregion
        }

        private void Cam7_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 7号相机回调函数 ******



            #endregion
        }

        private void Cam8_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 8号相机回调函数 ******



            #endregion
        }

        private void Cam9_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 9号相机回调函数 ******



            #endregion
        }

        private void Cam10_CallbackPro(Object sender, ImageGrabbedEventArgs e)
        {
            #region   ****** 10号相机回调函数 ******



            #endregion
        }

        #endregion
        #region **** 公开函数 *****
        public void Reset(string id, int aR, int aC)
        {
            currentRow = 0;
            currentCloumn = 0;
            batch = new Wafers();
            batch.BasePath = @"D:\Ngs\" + id;
            batch.Id = id;
            batch.AllColumn = aC;//= new List<Ng>();
            batch.AllRow = aR;
            batch.wafers = new List<OneWafer>();
        }
        public Wafers Done()
        {
            return batch;
        }

        #endregion 
        #region **** 内部函数 *****

        //将相机抓取到的图像转换成Bitmap位图
        private Bitmap GrabResult2Bmp(IGrabResult grabResult)
        {
            //basler里用于将相机采集的图像转换成位图
            PixelDataConverter pxConvert = new PixelDataConverter();
            try
            {
                Bitmap b = new Bitmap(grabResult.Width, grabResult.Height, PixelFormat.Format24bppRgb);
                BitmapData bmpData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, b.PixelFormat);
                pxConvert.OutputPixelFormat = PixelType.BGR8packed;
                IntPtr bmpIntpr = bmpData.Scan0;
                pxConvert.Convert(bmpIntpr, bmpData.Stride * b.Height, grabResult);
                b.UnlockBits(bmpData);
                bmpData = null;
                return b;
            }
            catch (Exception er) { }
            finally
            {
                pxConvert.Dispose();
            }
            return null;
        }
        private bool IsColorPixelFormat(string strPixelFormat)//wells0158
        {
            bool ret = false;

            switch (strPixelFormat)
            {
                case "Mono8":
                case "Mono10":
                case "Mono10Packed":
                case "Mono12Packed":
                case "Mono12":
                    ret = false;
                    break;
                case "RGB8Planar":
                case "YUV411Packed":
                case "RGB10V2Packed":
                case "RGB10V1Packed":
                case "BGR12Packed":
                case "RGB12Packed":
                case "BGR10Packed":
                case "RGB10Packed":
                case "BGRA8Packed":
                case "RGBA8Packed":
                case "BGR8Packed":
                case "RGB8Packed":
                case "BayerBG12":
                case "BayerGB12":
                case "BayerRG12":
                case "BayerGR12":
                case "BayerBG10":
                case "BayerGB10":
                case "BayerRG10":
                case "BayerGR10":
                case "BayerBG8":
                case "BayerGB8":
                case "BayerRG8":
                case "BayerGR8":
                case "Mono16":
                case "YUV422Packed":
                case "YUV444Packed":
                case "RGB10Planar":
                case "YCbCr422_8":
                case "BGR8":
                case "RGB8":
                case "BayerBG12p":
                case "BayerGB12p":
                case "BayerRG12p":
                case "BayerGR12p":
                case "Mono12p":
                case "BayerBG10p":
                case "BayerGB10p":
                case "BayerRG10p":
                case "BayerGR10p":
                case "Mono10p":
                case "Mono8Signed":
                case "RGB12V1Packed":
                case "BayerBG16":
                case "BayerGB16":
                case "BayerRG16":
                case "BayerGR16":
                case "BayerBG12Packed":
                case "BayerRG12Packed":
                case "BayerGR12Packed":
                case "BayerGB12Packed":
                case "YUV422_YUYV_Packed":
                case "RGB16Planar":
                case "RGB12Planar":
                case "RGB16Packed":
                    ret = true;
                    break;
                default:
                    ret = false;
                    break;
            }

            return ret;
        }

        private void registCamCallback(int icamNumber)
        {
            if (bRegistCallback[icamNumber])
                return;

            if (icamNumber == 1)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam1_CallbackPro;
            if (icamNumber == 2)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam2_CallbackPro;
            if (icamNumber == 3)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam3_CallbackPro;
            if (icamNumber == 4)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam4_CallbackPro;
            if (icamNumber == 5)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam5_CallbackPro;
            if (icamNumber == 6)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam6_CallbackPro;
            if (icamNumber == 7)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam7_CallbackPro;
            if (icamNumber == 8)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam8_CallbackPro;
            if (icamNumber == 9)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam9_CallbackPro;
            if (icamNumber == 10)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed += Cam10_CallbackPro;

            bRegistCallback[icamNumber] = true;
        }

        private void unregistCamCallback(int icamNumber)
        {
            if (!bRegistCallback[icamNumber])
                return;

            if (icamNumber == 1)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam1_CallbackPro;
            if (icamNumber == 2)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam2_CallbackPro;
            if (icamNumber == 3)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam3_CallbackPro;
            if (icamNumber == 4)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam4_CallbackPro;
            if (icamNumber == 5)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam5_CallbackPro;
            if (icamNumber == 6)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam6_CallbackPro;
            if (icamNumber == 7)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam7_CallbackPro;
            if (icamNumber == 8)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam8_CallbackPro;
            if (icamNumber == 9)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam9_CallbackPro;
            if (icamNumber == 10)
                myDevices[icamNumber].StreamGrabber.ImageGrabbed -= Cam10_CallbackPro;

            bRegistCallback[icamNumber] = false;
        }

        #endregion
    }
}